// cSpell:words mysqls keepalive
export interface MySQLConfig {
    name: string
    host: string
    user: string
    password: string
    database: string
    connectionLimit?: number
}

export interface MongoDBConfig {
    name: string
    url: string
}

export interface SubApp {
    label: string
    origins: string[]
}

export type WebErrorCatcher = () => void

export interface SSOServerClient {
    acceptTokenUrl: string
    key: string
}

export interface SSOServerConfig {
    clients: {[origin: string]: SSOServerClient}
}

export interface OriginConfigItem {
    description?: string
    ssoServer: string
    defaultCallbackUrl: string
    ssoKey: string
}

export interface OriginConfig {
    [origin: string]: OriginConfigItem
}

export interface RedisClientOpts {
    host?: string
    port?: number
    path?: string
    url?: string
    parser?: string
    string_numbers?: boolean
    return_buffers?: boolean
    detect_buffers?: boolean
    socket_keepalive?: boolean
    no_ready_check?: boolean
    enable_offline_queue?: boolean
    retry_max_delay?: number
    connect_timeout?: number
    max_attempts?: number
    retry_unfulfilled_commands?: boolean
    auth_pass?: string
    password?: string
    db?: string | number
    family?: string
    rename_commands?: { [command: string]: string } | null
    tls?: any
    prefix?: string
}

export interface IConfig {
    metaFile: string
    serverPort: number
    serverSocketTimeout: number
    cookieKey: string
    serverPugPath: string
    uploadPath: string
    httpBodyMaxFieldsSize: number
    fileDefaultMaxSize: number
    imageDefaultMaxSize: number
    sessionExpireAtServer: number
    usernameFields: string[]
    mongoDatabases: MongoDBConfig[]
    mysqls?: MySQLConfig[],
    redis: any,
    enableRedis?: boolean,
    passwordFormat: RegExp
    fileDir: string
    fileDownloadPrefix: string
    cluster?: boolean
    workerNum?: number
    ssoOff?: boolean
    sso?: string
    subApps?: SubApp[]
    ssoServer: SSOServerConfig
    originConfigs: OriginConfig
    logConfigs: any
    errorCatcher: WebErrorCatcher | null
    tuningFileDir?: string
    preprocess: () => void
}

const DEFAULT_CONFIG: IConfig = {
    metaFile: "",
    serverPort: 8090,
    serverSocketTimeout: 10 * 60 * 1000,
    cookieKey: "xxx",
    serverPugPath: "",
    uploadPath: "",
    httpBodyMaxFieldsSize: 6 * 1024 * 1024,
    fileDefaultMaxSize: 6 * 1024 * 1024,
    imageDefaultMaxSize: 2 * 1024 * 1024,
    sessionExpireAtServer: 1000 * 60 * 60 * 24 * 15, //  15 day
    usernameFields: ["username"],
    enableRedis: false,
    mongoDatabases: [{
        name: "main",
        url: "mongodb://localhost:27017/demo"
    }],
    redis: {},
    passwordFormat: /^([a-zA-Z0-9]){8,20}$/,
    fileDir: "",
    fileDownloadPrefix: "/r/",
    cluster: false,
    workerNum: 2,
    ssoServer: {clients: {}},
    originConfigs: {},
    logConfigs: {},
    errorCatcher: null,
    preprocess
}

export default DEFAULT_CONFIG


function preprocess() {
    if (DEFAULT_CONFIG.sso && DEFAULT_CONFIG.subApps) {
        console.log("Preprocess config: sso & subApps")

        const ssoKey = Date.now().toString()

        const originConfigs: OriginConfig = {}

        for (const subApp of DEFAULT_CONFIG.subApps) {
            for (const origin of subApp.origins) {
                originConfigs[origin] = {
                    ssoServer: DEFAULT_CONFIG.sso,
                    defaultCallbackUrl: origin,
                    ssoKey
                }
            }
        }

        const ssoClients: {[origin: string]: SSOServerClient} = {}
        for (const subApp of DEFAULT_CONFIG.subApps) {
            for (const origin of subApp.origins) {
                ssoClients[origin] = {
                    acceptTokenUrl: origin + "/api/c/sso/client/token",
                    key: ssoKey
                }
            }
        }

        DEFAULT_CONFIG.originConfigs = originConfigs
        DEFAULT_CONFIG.ssoServer = {clients: ssoClients}
    }
}
